/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package service.reportCenter.multiReport;

import com.openbrew.openbrewrf.Equipment;
import com.openbrew.openbrewrf.EquipmentCleaningHistory;
import com.openbrew.openbrewrf.Fv;
import com.openbrew.openbrewrf.VesselCleaningHistory;
import com.openbrew.openbrewrf.VesselCleaningProcedure;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
import pdf.GenericPDFCreator;
import service.reportCenter.brewForecastReport.BFDetailReport;
import service.reportCenter.brewForecastReport.BFReport;
import service.reportCenter.brewForecastReport.BrewForecastReportREST;

/**
 *
 * @author chapmand
 */
@Stateless
@Path("com.openbrew.openbrewrf.multireport")
public class MultiReportFacadeREST {
    @EJB
    private BrewForecastReportREST brewForecastReportREST;
    final DateFormat fullDate = new SimpleDateFormat("MM/dd/yy", Locale.US);
    final NumberFormat f2 = new DecimalFormat("#0.00");

    @PersistenceContext(unitName = "com.openBrew_openBrewRF_war_1.0PU")
    private EntityManager em;

    public MultiReportFacadeREST() {
    }

    @GET
    @Path("getPDFReport/{reportID}")
    @Produces({"application/pdf"})
    public StreamingOutput getPDFReport(@PathParam("reportID") final Integer reportID) {
        return new StreamingOutput() {
            @Override
            public void write(OutputStream output) throws IOException, WebApplicationException {
                try {
                    final GenericPDFCreator recppdf = new GenericPDFCreator();
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    recppdf.createStringPDF(outputStream, getStringReport(reportID), ReportType.getType(reportID).toString());
                    byte[] bytes = outputStream.toByteArray();
                    output.write(bytes);
                } catch (IOException e) {
                    throw new WebApplicationException(e);
                }
            }
        };
    }

    @GET
    @Path("getStringReport/{reportID}")
    @Produces("text/plain")
    public String getStringReport(@PathParam("reportID") Integer reportID) {
        String result = "";
        if(reportID == ReportType.BREW_FORECAST.getType()){
            return runBrewForecastReport();
        } else if(reportID == ReportType.CLEANING_REP.getType()){
            return runCleaningCheckWithAbsoluteDisplay();
        }
        return result;
    }
        
    public String runBrewForecastReport(){
        Date today = new Date();
        List<BFReport> forecastReports = brewForecastReportREST.find(today, 90);
        String display = "";
        //run a check of vessels to see if any are over due or need to be cleaned.
        for(BFReport bf : forecastReports){
            display += bf.getBeerName() + " Shortages\n";
            for(BFDetailReport bfd : bf.getDetails()){
                display += "    " + f2.format(bfd.getVol()) + " BBL on " 
                    + fullDate.format(bfd.getDueDate()) + "      Est. Brew Date: " 
                    + fullDate.format(bfd.getBrewDate())+ "\n";
            }
            display += "\n\n";
        }
        return display;
    }

    public String runCleaningCheckWithAbsoluteDisplay() {
        Date date = new Date();
        Date today = new Date(date.getTime());
        String display = "";
        //run a check of vessels to see if any are over due or need to be cleaned.
        for (Fv vessel : getAllVessels(em)) {
            //check each procedure assigned to vessel against history.
            if (vessel.getVcpCollection() != null) {
                for (VesselCleaningProcedure vcpItem : vessel.getVcpCollection()) {
                    //check history to see if it is time for a cleaning.
                    Date olddate = null;
                    for (final VesselCleaningHistory vchItem : getAllVesselCleaningHistory(em)) {
                        if ((vchItem.getVCVesselID().getFvid() == vessel.getFvid()) && (vchItem.getVCProcedureID().getVcpid() == vcpItem.getVcpid())) {
                            olddate = vchItem.getVCDate();
                        }
                    }
                    if (olddate != null) {
                        //calculate next date based on days.
                        int daysElapsed = diffInDays(olddate, today);
                        if (daysElapsed >= vcpItem.getVCPRepeatDays()) {
                            display += "Vessel: " + vessel.getFVDesg() + " is due for "
                                    + vcpItem.getVCPDesc() + " immediately!\n";
                        }
                    } else {
                        display += "Vessel: " + vessel.getFVDesg() + " is due for "
                                + vcpItem.getVCPDesc() + " immediately! (Never performed on tank)\n";
                    }
                }
            }
        }
        display += "\n\n";
        for (Equipment equip : getAllEquipment(em)) {
            //check each procedure assigned to vessel against history.
            if (equip.getVcpCollection() != null) {
                for (VesselCleaningProcedure vcpItem : equip.getVcpCollection()) {
                    //check history to see if it is time for a cleaning.
                    java.util.Date olddate = null;
                    for (final EquipmentCleaningHistory echItem : getAllEquipmentCleaningHistory(em)) {
                        if ((echItem.getECVesselID().getEquipID() == equip.getEquipID()) && (echItem.getECProcedureID().getVcpid() == vcpItem.getVcpid())) {
                            olddate = echItem.getECDate();
                        }
                    }
                    if (olddate != null) {
                        //calculate next date based on days.
                        int daysElapsed = diffInDays(olddate, today);
                        if (daysElapsed >= vcpItem.getVCPRepeatDays()) {
                            display += "Equipment: " + equip.getEquipName() + " is due for "
                                    + vcpItem.getVCPDesc() + " immediately!\n";
                        }
                    } else {
                        display += "Equipment: " + equip.getEquipName() + " is due for "
                                + vcpItem.getVCPDesc() + " immediately! (Never performed on tank)\n";
                    }
                }
            }
        }
        return display;
    }
        
    private int diffInDays(java.util.Date from, java.util.Date to) {
        final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * 1000;
        return (int) ((to.getTime() - from.getTime()) / MILLISECONDS_IN_DAY);
    }

    private List<Fv> getAllVessels(final EntityManager en){
        TypedQuery<Fv> query = en.createNamedQuery("Fv.findAll", Fv.class);
        return query.getResultList();
    }
    
    private List<Equipment> getAllEquipment(final EntityManager en){
        TypedQuery<Equipment> query = en.createNamedQuery("Equipment.findAll", Equipment.class);
        return query.getResultList();
    }
    
    private List<VesselCleaningHistory> getAllVesselCleaningHistory(final EntityManager en){
        TypedQuery<VesselCleaningHistory> query = en.createNamedQuery("VesselCleaningHistory.findAll", VesselCleaningHistory.class);
        return query.getResultList();
    }
    
    private List<EquipmentCleaningHistory> getAllEquipmentCleaningHistory(final EntityManager en){
        TypedQuery<EquipmentCleaningHistory> query = en.createNamedQuery("EquipmentCleaningHistory.findAll", EquipmentCleaningHistory.class);
        return query.getResultList();
    }
    

    protected EntityManager getEntityManager() {
        return em;
    }
}
